package api

import (
	"demo/api/handlers"
	"demo/infra/errors"
	"demo/infra/middleware/auth"
	"demo/infra/middleware/transform"
	"html/template"
	"net/http"
	"path/filepath"
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

// 定义404页面内容常量
const Page404Content = `<!DOCTYPE html>
<html>
<head>
    <title>404 Not Found</title>
</head>
<body>
    <h1>404 Not Found</h1>
    <p>The requested URL was not found on this server.</p>
</body>
</html>`

type Router struct {
	convertUrlHandle    *api.ConvertUrlHandler
	authHandle          *api.AuthHandler
	transformMiddleware *transform.TransformMiddleware
	authMiddleware      *auth.AuthMiddleware
}

func NewRouter(convertUrlHandle *api.ConvertUrlHandler, authHandle *api.AuthHandler,
	transformMiddleware *transform.TransformMiddleware, authMiddleware *auth.AuthMiddleware) *Router {
	return &Router{convertUrlHandle: convertUrlHandle, authHandle: authHandle, transformMiddleware: transformMiddleware,
		authMiddleware: authMiddleware}
}

func (ro Router) SetupRouter() *gin.Engine {
	gin.SetMode(gin.ReleaseMode)
	r := gin.New()
	// 关键：注册模板函数（必须在加载模板前注册）
	r.SetFuncMap(template.FuncMap{
		"minusOne": func(n int) int { return n - 1 },
		"plusOne":  func(n int) int { return n + 1 },
		"sub":      func(a, b int) int { return a - b },
		"add":      func(a, b int) int { return a + b },
		"max": func(a, b int) int {
			if a > b {
				return a
			} else {
				return b
			}
		},
		"min": func(a, b int) int {
			if a < b {
				return a
			} else {
				return b
			}
		},
		"seq": func(start, end int) []int { // 生成连续整数切片
			var res []int
			for i := start; i <= end; i++ {
				res = append(res, i)
			}
			return res
		},
	})
	// 加载模板（必须在注册函数后）
	// 解析 templates 目录下所有 .html 文件（支持模板继承）
	r.LoadHTMLGlob("infra/templates/*.html")
	// 注册全局中间件
	r.Use(
		gin.Recovery(),
		errors.ErrorHandler(),
		setupCors(),
	)
	// 静态资源配置
	staticPath, _ := filepath.Abs("infra/static")
	r.Static("/static", staticPath)
	// 404处理
	r.NoRoute(handle404)
	// 注册路由组
	ro.registerBaseRoutes(r)
	ro.registerPublicRoutes(r)
	ro.registerProtectedRoutes(r)
	ro.registerShortLinkRoutes(r)
	return r
}

// 配置CORS
func setupCors() gin.HandlerFunc {
	return cors.New(cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
		ExposeHeaders:    []string{"Content-Length", "X-Total-Count"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	})
}

// 404处理
func handle404(c *gin.Context) {
	c.Status(http.StatusNotFound)
	_, _ = c.Writer.WriteString(Page404Content)
}

// 基础路由
func (r *Router) registerBaseRoutes(engine *gin.Engine) {
	engine.GET("/", func(c *gin.Context) {
		c.Redirect(http.StatusSeeOther, "/auth/loginPage")
	})
	engine.GET("/health", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"status": "healthy"})
	})
}

// 公共路由（无需登录）
func (r *Router) registerPublicRoutes(engine *gin.Engine) {
	authGroup := engine.Group("/auth")
	{
		authGroup.GET("/loginPage", r.authHandle.LoginPage)
		authGroup.POST("/login", r.authHandle.Login)
		authGroup.GET("/registerPage", r.authHandle.RegisterPage)
		authGroup.POST("/register", r.authHandle.Register)
		authGroup.GET("/logout", r.authHandle.Logout)
	}
}

// 受保护路由（需登录）
func (r *Router) registerProtectedRoutes(engine *gin.Engine) {
	protected := engine.Group("/")
	protected.Use(r.authMiddleware.RequiredLogin())
	{
		urlGroup := protected.Group("/url")
		{
			urlGroup.GET("/createPage", r.convertUrlHandle.CreateUrlPage)
			urlGroup.POST("/create", r.convertUrlHandle.CreateUrlMap)
			urlGroup.POST("/update", r.convertUrlHandle.ReplaceUrlMap)
			urlGroup.POST("/pageQuery", r.convertUrlHandle.UrlMapPageQuery)
			urlGroup.GET("/list", r.convertUrlHandle.UrListPage)
			urlGroup.POST("/stats", r.convertUrlHandle.UrlStatisticsPageQuery)
		}
		// 用户中心路由
		userGroup := protected.Group("/user")
		{
			userGroup.GET("/profile", r.authHandle.Profile)
		}
	}
}

// 短链路由
func (ro *Router) registerShortLinkRoutes(engine *gin.Engine) {
	engine.GET("/:code", ro.transformMiddleware.ExecuteMiddleware()...)
}
